package multithreading.a8;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;

public class Deadlock {
    public static void main(String[] args) throws InterruptedException {
        ResourceA resourceA = new ResourceA();
        ResourceB resourceB = new ResourceB();
        resourceA.resourceB = resourceB;
        resourceB.resourceA = resourceA;
        DeadThread1 deadThread1 = new DeadThread1();
        DeadThread2 deadThread2 = new DeadThread2();
        deadThread1.resourceA = resourceA;
        deadThread2.resourceB = resourceB;
        deadThread1.start();
        deadThread2.start();

        Thread.sleep(1000);
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        long[] deadlockedThreads = threadMXBean.findDeadlockedThreads();
        if(deadlockedThreads != null) {
            ThreadInfo[] threadInfo = threadMXBean.getThreadInfo(deadlockedThreads);
            for (ThreadInfo info : threadInfo) {
                System.out.println(info);
            }
        }
    }
}

class DeadThread1 extends Thread {
    ResourceA resourceA;
    @Override
    public void run() {
        System.out.println(resourceA.getI());
    }
}

class DeadThread2 extends Thread {
    ResourceB resourceB;
    @Override
    public void run() {
        System.out.println(resourceB.getI());
    }
}

class ResourceA {
    ResourceB resourceB;
    public synchronized int getI() {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return resourceB.returnI();
    }
    public synchronized int returnI() {
        return 1;
    }
}

class ResourceB {
    ResourceA resourceA;
    public synchronized int getI() {
        return resourceA.returnI();
    }
    public synchronized int returnI() {
        return 2;
    }
}